﻿using System;
using System.Collections.Generic;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using YJKArchUtils.Utils;
using YJKRevitKernel.ElementSearchUtility.LinkDocumentSuite;
using YJKGeometryFuncs;
using YJKPatternSign.StairsRoomSection.Kit;

namespace YJKPatternSign.StairsRoomSection.DataDefine
{
	public class SignElementData
	{
		public Line BaseLineLayer
		{
			get
			{
				return this.m_BaseLineLayer;
			}
		}

		public Line BaseLineRun
		{
			get
			{
				return this.m_BaseLineRun;
			}
		}

		public XYZ DimNormal
		{
			get
			{
				return this.m_DimNormal;
			}
		}

		public List<BaseLinkDocumentResultBean> LstDoorCut
		{
			get
			{
				return this.m_lstDoorCut;
			}
		}

		public List<BaseLinkDocumentResultBean> LstDoorSee
		{
			get
			{
				return this.m_lstDoorSee;
			}
		}

		public List<BaseLinkDocumentResultBean> LstGrid
		{
			get
			{
				return this.m_lstGrid;
			}
		}

		public List<BaseLinkDocumentResultBean> LstLevel
		{
			get
			{
				return this.m_lstLevel;
			}
		}

		public List<BaseLinkDocumentResultBean> LstStairs
		{
			get
			{
				return this.m_lstStairs;
			}
		}

		public Dictionary<int, List<BaseLinkDocumentResultBean>> DicWall
		{
			get
			{
				return this.m_dicWall;
			}
		}

		public List<BaseLinkDocumentResultBean> LstWindowCut
		{
			get
			{
				return this.m_lstWindowCut;
			}
		}

		public List<BaseLinkDocumentResultBean> LstWindowSee
		{
			get
			{
				return this.m_lstWindowSee;
			}
		}

		public List<BaseLinkDocumentResultBean> LstStairsRailing
		{
			get
			{
				return this.m_lstStairsRailing;
			}
		}

		public Dictionary<double, List<BaseLinkDocumentResultBean>> LstFloorBottomElevator
		{
			get
			{
				return this.m_DicFloorBottomElevator;
			}
		}

		public Dictionary<string, double> DicElevator2LayerName
		{
			get
			{
				return this.m_dicElevator2LayerName;
			}
		}

		public List<BaseLinkDocumentResultBean> LstFloor
		{
			get
			{
				return this.m_lstFloor;
			}
		}

		public SignElementData(SectionViewData view, prepareElementsCls PrepareObj)
		{
			this.m_secViewData = view.clone();
			this.m_doc = this.m_secViewData.SectionView.Document;
			this.m_lstFloor.AddRange(PrepareObj.LstFloor);
			this.m_lstGrid.AddRange(PrepareObj.LstGrid);
			this.m_lstLevel.AddRange(PrepareObj.LstLevel);
			this.m_lstStairs.AddRange(PrepareObj.LstStairs);
			this.m_lstStairsRailing.AddRange(PrepareObj.LstRailing);
			this.FilterWalls(PrepareObj.LstWall);
			this.FilterWindowOrDoorIfCut(PrepareObj.LstDoor, ref this.m_lstDoorCut, ref this.m_lstDoorSee);
			this.FilterWindowOrDoorIfCut(PrepareObj.LstWindow, ref this.m_lstWindowCut, ref this.m_lstWindowSee);
			ElementClassFilter filter = new ElementClassFilter(typeof(Wall));
			List<BaseLinkDocumentResultBean> lstWallSee = PrepareObj.FilterElemByViewAndKind(filter, false);
			this.FilterWindowOrDoorIfCovered(lstWallSee, ref this.m_lstDoorSee);
			this.FilterWindowOrDoorIfCovered(lstWallSee, ref this.m_lstWindowSee);
		}

		public bool InitSignElementData()
		{
			if (!this.GetBaseLineAndNormal())
			{
				return false;
			}
			this.GetFloorBottomElevator();
			this.GetLayerNameAndElevator();
			return true;
		}

		private void FilterWindowOrDoorIfCovered(List<BaseLinkDocumentResultBean> lstWallSee, ref List<BaseLinkDocumentResultBean> lstWindowOrDoorSee)
		{
			foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean in lstWallSee)
			{
				Curve curve = this.GetWallCvToCurrentDoc(baseLinkDocumentResultBean);
				if (!(curve == null))
				{
					double wallElevationTop = this.GetWallElevationTop(baseLinkDocumentResultBean);
					double wallElevationBottom = this.GetWallElevationBottom(baseLinkDocumentResultBean);
					for (int i = 0; i < lstWindowOrDoorSee.Count; i++)
					{
						if (!(baseLinkDocumentResultBean.UseElement.Id == (lstWindowOrDoorSee[i].UseElement as FamilyInstance).Host.Id))
						{
							Line lineFormDoorToSecLine = this.GetLineFormDoorToSecLine(lstWindowOrDoorSee[i]);
							if (!(lineFormDoorToSecLine == null))
							{
								double doorOrWindowHeight = this.GetDoorOrWindowHeight(lstWindowOrDoorSee[i]);
								double num = lineFormDoorToSecLine.GetEndPoint(0).Z;
								if (!YJKArchUtils.Utils.Geometry.LessThan(wallElevationTop, num + doorOrWindowHeight) && !YJKArchUtils.Utils.Geometry.LessThan(num, wallElevationBottom))
								{
									num = lineFormDoorToSecLine.GetEndPoint(0).Z - curve.GetEndPoint(0).Z;
									Transform transform = Transform.CreateTranslation(new XYZ(0.0, 0.0, num));
									curve = curve.CreateTransformed(transform);
									IntersectionResultArray intersectionResultArray = null;
									curve.Intersect(lineFormDoorToSecLine, out intersectionResultArray);
									if (intersectionResultArray != null && intersectionResultArray.Size != 0)
									{
										lstWindowOrDoorSee.RemoveAt(i);
										i--;
									}
								}
							}
						}
					}
				}
			}
		}

		private Curve GetWallCvToCurrentDoc(BaseLinkDocumentResultBean bean)
		{
			Curve result = null;
			try
			{
				Document document = bean.UseElement.Document;
				Curve curve = ((bean.UseElement as Wall).Location as LocationCurve).Curve;
				Transform totalTransform = bean.GetTotalTransform();
				result = curve.CreateTransformed(totalTransform);
			}
			catch
			{
			}
			return result;
		}

		private double GetWallElevationTop(BaseLinkDocumentResultBean beanWall)
		{
			Document document = beanWall.UseElement.Document;
			Wall wall = beanWall.UseElement as Wall;
			ElementId elementId = wall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).AsElementId();
			double result;
			if (ElementId.InvalidElementId != elementId)
			{
				double elevation = (RevitVersionFuncs.GetElement(document, elementId) as Level).Elevation;
				double num = wall.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).AsDouble();
				result = elevation + num;
			}
			else
			{
				result = wall.get_Parameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM).AsDouble() + this.GetWallElevationBottom(beanWall);
			}
			return result;
		}

		private double GetWallElevationBottom(BaseLinkDocumentResultBean beanWall)
		{
			Document document = beanWall.UseElement.Document;
			Wall wall = beanWall.UseElement as Wall;
			double result = 0.0;
			ElementId elementId = wall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).AsElementId();
			if (ElementId.InvalidElementId != elementId)
			{
				double elevation = (RevitVersionFuncs.GetElement(document, elementId) as Level).Elevation;
				double num = wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).AsDouble();
				result = elevation + num;
			}
			return result;
		}

		private Line GetLineFormDoorToSecLine(BaseLinkDocumentResultBean bean)
		{
			Line result = null;
			try
			{
				XYZ xyz = (bean.UseElement.Location as LocationPoint).Point;
				xyz = bean.GetTotalTransform().OfPoint(xyz);
				XYZ xyz2 = this.m_secViewData.m_viewDir.Normalize();
				XYZ xyz3 = xyz + xyz2 * 1000.0;
				result = Line.CreateBound(xyz, xyz3);
			}
			catch (Exception)
			{
			}
			return result;
		}

		private double GetDoorOrWindowHeight(BaseLinkDocumentResultBean bean)
		{
			double result = Common.MMToFeet(2000.0);
			try
			{
				FamilyInstance familyInstance = bean.UseElement as FamilyInstance;
				double num = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_HEAD_HEIGHT_PARAM).AsDouble();
				double num2 = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_SILL_HEIGHT_PARAM).AsDouble();
				result = num - num2;
			}
			catch (Exception)
			{
			}
			return result;
		}

		private void FilterWindowOrDoorIfCut(List<BaseLinkDocumentResultBean> lstAll, ref List<BaseLinkDocumentResultBean> lstCut, ref List<BaseLinkDocumentResultBean> lstSee)
		{
			foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean in lstAll)
			{
				Curve secLine = this.m_secViewData.m_SecLine;
				Transform totalTransform = baseLinkDocumentResultBean.GetTotalTransform();
				Line line = secLine.CreateTransformed(totalTransform.Inverse) as Line;
				Document document = baseLinkDocumentResultBean.UseElement.Document;
				Element useElement = baseLinkDocumentResultBean.UseElement;
				XYZ point = (useElement.Location as LocationPoint).Point;
				if (this.CheckDoorOrWindowsInView(baseLinkDocumentResultBean))
				{
					Curve curve = (((baseLinkDocumentResultBean.UseElement as FamilyInstance).Host as Wall).Location as LocationCurve).Curve;
					double num = line.GetEndPoint(0).Z - curve.GetEndPoint(0).Z;
					Transform transform = Transform.CreateTranslation(new XYZ(0.0, 0.0, num));
					Curve curve2 = curve.CreateTransformed(transform);
					IntersectionResultArray intersectionResultArray = null;
					curve2.Intersect(line, out intersectionResultArray);
					if (intersectionResultArray == null || intersectionResultArray.Size == 0)
					{
						lstSee.Add(baseLinkDocumentResultBean);
					}
					else
					{
						Parameter parameter = (document.GetElement(useElement.GetTypeId()) as FamilySymbol).get_Parameter(BuiltInParameter.CASEWORK_WIDTH);
						if (parameter != null)
						{
							double val = parameter.AsDouble() / 2.0;
							line.GetEndPoint(0);
							if (YJKGeometryFuncs.Geometry.LessThan((SignCommon.ChangeLineElevator(line, point.Z) as Line).Distance(point), val))
							{
								lstCut.Add(baseLinkDocumentResultBean);
							}
						}
					}
				}
			}
		}

		private bool CheckDoorOrWindowsInView(BaseLinkDocumentResultBean bean)
		{
			Transform totalTransform = bean.GetTotalTransform();
			Element useElement = bean.UseElement;
			XYZ point = (useElement.Location as LocationPoint).Point;
			BoundingBoxXYZ boundingBoxXYZ = SectionViewData.transformMinAndMaxPt(this.m_secViewData.MinPt, this.m_secViewData.MaxPt, totalTransform.Inverse);
			XYZ min = boundingBoxXYZ.Min;
			XYZ max = boundingBoxXYZ.Max;
			XYZ point2 = ((useElement as FamilyInstance).Location as LocationPoint).Point;
			return YJKGeometryFuncs.Geometry.Lessthan_Or_Equal(min.X, point2.X) && YJKGeometryFuncs.Geometry.Lessthan_Or_Equal(min.Y, point2.Y) && YJKGeometryFuncs.Geometry.Lessthan_Or_Equal(min.Z, point2.Z) && YJKGeometryFuncs.Geometry.Lessthan_Or_Equal(point2.X, max.X) && YJKGeometryFuncs.Geometry.Lessthan_Or_Equal(point2.Y, max.Y) && YJKGeometryFuncs.Geometry.Lessthan_Or_Equal(point2.Z, max.Z);
		}

		private void FilterWalls(List<BaseLinkDocumentResultBean> lstBean)
		{
			foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean in lstBean)
			{
				int wallBottomElev = this.GetWallBottomElev(baseLinkDocumentResultBean);
				if (this.m_dicWall.ContainsKey(wallBottomElev))
				{
					this.m_dicWall[wallBottomElev].Add(baseLinkDocumentResultBean);
				}
				else
				{
					List<BaseLinkDocumentResultBean> list = new List<BaseLinkDocumentResultBean>();
					list.Add(baseLinkDocumentResultBean);
					this.m_dicWall.Add(wallBottomElev, list);
				}
			}
			this.m_dicWall = (from p in this.m_dicWall
			orderby p.Key
			select p).ToDictionary((KeyValuePair<int, List<BaseLinkDocumentResultBean>> p) => p.Key, (KeyValuePair<int, List<BaseLinkDocumentResultBean>> o) => o.Value);
		}

		public bool GetBaseLineAndNormal()
		{
			return this.LstStairs.Count != 0 && this.GetBaseLineAndNormalByStairs();
		}

		private bool GetBaseLineAndNormalByStairs()
		{
			this.m_DimNormal = this.m_secViewData.SectionView.RightDirection;
			BaseLinkDocumentResultBean baseLinkDocumentResultBean = this.m_lstStairs[0];
			SectionViewData sectionViewData = null;
			CommonFun.TransformViewData(baseLinkDocumentResultBean, this.m_secViewData, out sectionViewData);
			XYZ rightDirection = sectionViewData.SectionView.RightDirection;
			Stairs stairs = baseLinkDocumentResultBean.UseElement as Stairs;
			double baseElevation = stairs.BaseElevation;
			Line line = SignCommon.ChangeLineElevator(sectionViewData.m_SecLine, baseElevation) as Line;
			if (!line.Direction.Normalize().IsAlmostEqualTo(rightDirection))
			{
				line = (line.CreateReversed() as Line);
			}
			List<Curve> stairsBoundary = this.GetStairsBoundary(stairs);
			List<XYZ> list = new List<XYZ>();
			SignCommon.GetIntersection(stairsBoundary, line, list);
			double num = double.MinValue;
			XYZ farthestPt = XYZ.Zero;
			if (list.Count > 0)
			{
				foreach (XYZ xyz in list)
				{
					double parameter = line.Project(xyz).Parameter;
					if (parameter > num)
					{
						num = parameter;
						farthestPt = baseLinkDocumentResultBean.GetTotalTransform().OfPoint(xyz);
					}
				}
				this.initBaseLineV(this.m_secViewData.SectionView.RightDirection, farthestPt);
				return true;
			}
			return false;
		}

		private List<Curve> GetStairsBoundary(Stairs stair)
		{
			List<ElementId> list = stair.GetStairsRuns() as List<ElementId>;
			List<ElementId> list2 = stair.GetStairsLandings() as List<ElementId>;
			List<Curve> list3 = new List<Curve>();
			foreach (ElementId elementId in list)
			{
				foreach (Curve item in (stair.Document.GetElement(elementId) as StairsRun).GetFootprintBoundary())
				{
					list3.Add(item);
				}
			}
			foreach (ElementId elementId2 in list2)
			{
				StairsLanding stairsLanding = stair.Document.GetElement(elementId2) as StairsLanding;
				foreach (Curve curve in stairsLanding.GetFootprintBoundary())
				{
					if (curve is Line)
					{
						list3.Add(curve);
					}
					else
					{
						StairsComponentConnection stairsComponentConnection = (stairsLanding.GetConnections() as List<StairsComponentConnection>).First<StairsComponentConnection>();
						XYZ xyz = YJKGeometryFuncs.Geometry.CalculatMidPoint(curve as Arc);
						ElementId peerElementId = stairsComponentConnection.PeerElementId;
						XYZ xyz2 = ((stair.Document.GetElement(peerElementId) as StairsRun).GetStairsPath().First<Curve>() as Line).Direction.CrossProduct(XYZ.BasisZ).Normalize();
						double radius = (curve as Arc).Radius;
						XYZ xyz3 = xyz + radius * xyz2;
						XYZ xyz4 = xyz - radius * xyz2;
						Line item2 = Line.CreateBound(xyz3, xyz4);
						list3.Add(item2);
					}
				}
			}
			return list3;
		}

		private void initBaseLineV(XYZ baseNormal, XYZ farthestPt)
		{
			List<BaseLinkDocumentResultBean> list = new List<BaseLinkDocumentResultBean>();
			if (this.DicWall.Count > 0)
			{
				list = this.DicWall.First<KeyValuePair<int, List<BaseLinkDocumentResultBean>>>().Value;
			}
			double num = double.MaxValue;
			BaseLinkDocumentResultBean baseLinkDocumentResultBean = null;
			foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean2 in list)
			{
				XYZ xyz = baseLinkDocumentResultBean2.GetTotalTransform().Inverse.OfPoint(farthestPt);
				XYZ xyz2 = baseLinkDocumentResultBean2.GetTotalTransform().Inverse.OfVector(baseNormal);
				XYZ xyz3 = xyz + xyz2 * 5.0;
				Line line = Line.CreateBound(xyz, xyz3);
				Curve curve = SignCommon.ChangeLineElevator(((baseLinkDocumentResultBean2.UseElement as Wall).Location as LocationCurve).Curve, xyz.Z);
				IntersectionResultArray intersectionResultArray = null;
				curve.Intersect(line, out intersectionResultArray);
				if (intersectionResultArray != null && intersectionResultArray.Size != 0)
				{
					double parameter = line.Project(intersectionResultArray.get_Item(0).XYZPoint).Parameter;
					if (num > parameter)
					{
						num = parameter;
						baseLinkDocumentResultBean = baseLinkDocumentResultBean2;
					}
				}
			}
			if (baseLinkDocumentResultBean != null)
			{
				double num2 = (baseLinkDocumentResultBean.UseElement as Wall).Width / 2.0 + num;
				farthestPt += num2 * baseNormal.Normalize();
			}
			XYZ xyz4 = farthestPt + 2.0 * SignCommon.m_dBaseLineInterval * baseNormal;
			xyz4 = new XYZ(xyz4.X, xyz4.Y, this.m_secViewData.DBottomElev);
			XYZ xyz5 = new XYZ(xyz4.X, xyz4.Y, this.m_secViewData.DTopElev);
			this.m_BaseLineLayer = Line.CreateBound(xyz4, xyz5);
			XYZ xyz6 = farthestPt + SignCommon.m_dBaseLineInterval * baseNormal;
			xyz6 = new XYZ(xyz6.X, xyz6.Y, this.m_secViewData.DBottomElev);
			XYZ xyz7 = new XYZ(xyz6.X, xyz6.Y, this.m_secViewData.DTopElev);
			this.m_BaseLineRun = Line.CreateBound(xyz6, xyz7);
		}

		private int GetWallBottomElev(BaseLinkDocumentResultBean bean)
		{
			double num = 0.0;
			Document document = bean.UseElement.Document;
			Wall wall = bean.UseElement as Wall;
			Parameter parameter = wall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT);
			if (parameter != null)
			{
				ElementId elementId = parameter.AsElementId();
				Level level = document.GetElement(elementId) as Level;
				num += level.Elevation;
			}
			parameter = wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET);
			if (parameter != null)
			{
				num += parameter.AsDouble();
			}
			num = SignCommon.TransformDouble(bean.GetTotalTransform(), num);
			return (int)num;
		}

		private void GetFloorBottomElevator()
		{
			foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean in this.LstFloor)
			{
				Transform totalTransform = baseLinkDocumentResultBean.GetTotalTransform();
				double num = (baseLinkDocumentResultBean.UseElement as Floor).get_Parameter(BuiltInParameter.STRUCTURAL_ELEVATION_AT_BOTTOM).AsDouble();
				num = SignCommon.TransformDouble(totalTransform, num);
				if (this.m_DicFloorBottomElevator.ContainsKey(num))
				{
					this.m_DicFloorBottomElevator[num].Add(baseLinkDocumentResultBean);
				}
				else
				{
					List<BaseLinkDocumentResultBean> list = new List<BaseLinkDocumentResultBean>();
					list.Add(baseLinkDocumentResultBean);
					this.m_DicFloorBottomElevator.Add(num, list);
				}
			}
			foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean2 in this.LstStairs)
			{
				Stairs stairs = baseLinkDocumentResultBean2.UseElement as Stairs;
				Document document = stairs.Document;
				Transform totalTransform2 = baseLinkDocumentResultBean2.GetTotalTransform();
				double baseElevation = stairs.BaseElevation;
				foreach (ElementId elementId in (stairs.GetStairsLandings() as List<ElementId>))
				{
					StairsLanding stairsLanding = document.GetElement(elementId) as StairsLanding;
					double num2 = baseElevation + stairsLanding.BaseElevation;
					num2 = SignCommon.TransformDouble(totalTransform2, num2);
					if (this.m_DicFloorBottomElevator.ContainsKey(num2))
					{
						this.m_DicFloorBottomElevator[num2].Add(baseLinkDocumentResultBean2);
					}
					else
					{
						List<BaseLinkDocumentResultBean> list2 = new List<BaseLinkDocumentResultBean>();
						list2.Add(baseLinkDocumentResultBean2);
						this.m_DicFloorBottomElevator.Add(num2, list2);
					}
				}
			}
			this.m_DicFloorBottomElevator = (from p in this.m_DicFloorBottomElevator
			orderby p.Key
			select p).ToDictionary((KeyValuePair<double, List<BaseLinkDocumentResultBean>> p) => p.Key, (KeyValuePair<double, List<BaseLinkDocumentResultBean>> p) => p.Value);
		}

		private void GetLayerNameAndElevator()
		{
			foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean in this.LstLevel)
			{
				Transform totalTransform = baseLinkDocumentResultBean.GetTotalTransform();
				Level level = baseLinkDocumentResultBean.UseElement as Level;
				double num = level.Elevation;
				num = SignCommon.TransformDouble(totalTransform, num);
				string name = level.Name;
				this.m_dicElevator2LayerName.Add(name, num);
			}
		}

		private Line m_BaseLineLayer;

		private Line m_BaseLineRun;

		private XYZ m_DimNormal = XYZ.BasisX;

		private Dictionary<double, List<BaseLinkDocumentResultBean>> m_DicFloorBottomElevator = new Dictionary<double, List<BaseLinkDocumentResultBean>>();

		private Dictionary<string, double> m_dicElevator2LayerName = new Dictionary<string, double>();

		private List<BaseLinkDocumentResultBean> m_lstFloor = new List<BaseLinkDocumentResultBean>();

		private List<BaseLinkDocumentResultBean> m_lstGrid = new List<BaseLinkDocumentResultBean>();

		private List<BaseLinkDocumentResultBean> m_lstLevel = new List<BaseLinkDocumentResultBean>();

		private List<BaseLinkDocumentResultBean> m_lstStairs = new List<BaseLinkDocumentResultBean>();

		private List<BaseLinkDocumentResultBean> m_lstStairsRailing = new List<BaseLinkDocumentResultBean>();

		private Dictionary<int, List<BaseLinkDocumentResultBean>> m_dicWall = new Dictionary<int, List<BaseLinkDocumentResultBean>>();

		private List<BaseLinkDocumentResultBean> m_lstWindowCut = new List<BaseLinkDocumentResultBean>();

		private List<BaseLinkDocumentResultBean> m_lstDoorCut = new List<BaseLinkDocumentResultBean>();

		private List<BaseLinkDocumentResultBean> m_lstWindowSee = new List<BaseLinkDocumentResultBean>();

		private List<BaseLinkDocumentResultBean> m_lstDoorSee = new List<BaseLinkDocumentResultBean>();

		private SectionViewData m_secViewData;

		private Document m_doc;
	}
}
